package com.atwulidun.linkedlist;

public class Josephu {
    public static void main(String[] args) {
        CircleSingleLinkedList circleSingleLinkedList = new CircleSingleLinkedList();
        circleSingleLinkedList.addBoy(5);
        circleSingleLinkedList.showBoy();

        circleSingleLinkedList.countBoy(1, 2);

    }
}

class CircleSingleLinkedList {
    private Boy first;// 一、创建一个first指针，一开始哪都不指向

    // 往环形链表中添加boy
    public void addBoy(int num) {
        // 对添加boy的个数进行校验
        if (num < 1) {
            System.out.println("添加的数量不合理！");
            return;
        }
        Boy curBoy = null;// 二、创建一个curBoy指针，一开始哪都不指向
        for (int i = 1; i <= num; i++) {
            Boy boy = new Boy(i);// 三、创建一个boy
            if (i == 1) {
                first = boy;// first指针是不动的，curBoy往后移动
                curBoy = boy;
                curBoy.setNext(first);
            } else {
                curBoy.setNext(boy);
                boy.setNext(first);// 此时已经形成一个闭环
                curBoy = boy;// curBoy要往后移动指向到boy
            }
        }
    }

    // 打印环形链表
    public void showBoy() {
        // 首先判断链表是否为空
        if (first == null) {
            System.out.println("链表为空!");
            return;
        }
        Boy curBoy = first;
        while (true) {
            System.out.println("小孩的编号为：" + curBoy.getNo());
            curBoy = curBoy.getNext();
            if (curBoy == first) {
                break;
            }
        }
    }

    // 求圈中boy的数量
    public int size() {
        if (first == null) {
            return 0;
        }
        Boy curBoy = first;
        int size = 0;
        while (true) {
            size++;
            curBoy = curBoy.getNext();
            if (curBoy == first) {
                break;
            }
        }
        return size;
    }

    /**
     *
     * @param startNo
     * 表示开始数数的位置
     * @param countNo
     * 表示数几下
     */
    public void countBoy(int startNo, int countNo) {
        // 首先对输入的参数进行校验
        if (first == null || countNo < 1 || startNo < 1 || startNo > size()) {
            System.out.println("输入参数有误，请重新输入！");
            return;
        }
        // 定义一个helper辅助指针，一开始指向first
        Boy helper = first;
        // 将helper指针移动到圈尾
        while (true) {
            if (helper.getNext() == first) {
                break;
            }
            helper = helper.getNext();
        }
        // 根据startNo参数将helper和first往后移动相应的位置
        for (int i = 0; i < startNo - 1; i++) {
            helper = helper.getNext();
            first = first.getNext();
        }
        // 根据countNo参数将helper和first往后再移动相应的位置，同时把first指向的结点删除
        while (true) {
            // 当first和helper相等时，说明圈中只剩下最后一个结点
            if (first == helper) {
                break;
            }
            for (int i = 0; i < countNo - 1; i++) {
                helper = helper.getNext();
                first = first.getNext();
            }
            System.out.println("出圈boy的编号为：" + first.getNo());// 此时first指向的结点即为出圈的结点
            first = first.getNext();// 将first移动到被删除结点的下一个结点，该节点也为下次开始数数的结点
            helper.setNext(first);
        }
        System.out.println("最后剩下的boy的编号为：" + first.getNo());
    }
}
class Boy {
    private int no;
    private Boy next;

    public Boy(int no) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public Boy getNext() {
        return next;
    }

    public void setNext(Boy next) {
        this.next = next;
    }
}